package com.msxt.interceptor;

import com.msxt.constant.JwtClaimsConstant;
import com.msxt.context.BaseContext;
import com.msxt.context.BaseContext.UserContext;
import com.msxt.properties.JwtProperties;
import com.msxt.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 支持跨域请求
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,request-source,Token, Origin,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization");

        // 处理OPTIONS请求
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        String token = request.getHeader(jwtProperties.getAdminTokenName());
        if (token == null) {
            // 尝试从URL参数获取token
            token = request.getParameter("token");
        }

        if (token == null || token.isEmpty()) {
            log.warn("未提供令牌 - URL: {}", request.getRequestURL());
            sendErrorResponse(response, 401, "未提供令牌");
            return false;
        }

        try {
            Claims claims = null;
            Long userId = null;
            String username = null;
            String role = null;
            String tableName = null;

            // 尝试使用管理员密钥解析
            try {
                claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
                userId = Long.valueOf(claims.get(JwtClaimsConstant.ADMNI_ID).toString());
            } catch (Exception e) {
                log.debug("管理员密钥解析失败，尝试用户密钥");

                // 尝试使用用户密钥解析
                try {
                    claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
                    userId = Long.valueOf(claims.get(JwtClaimsConstant.YOONGHU_ID).toString());
                } catch (Exception ex) {
                    log.debug("用户密钥解析失败，尝试商家密钥");

                    // 尝试使用商家密钥解析
                    claims = JwtUtil.parseJWT(jwtProperties.getShangjiaSecretKey(), token);
                    userId = Long.valueOf(claims.get(JwtClaimsConstant.SHANGJIA_ID).toString());
                }
            }

            // 获取公共声明
            username = claims.get(JwtClaimsConstant.USERNAME, String.class);
            role = claims.get(JwtClaimsConstant.ROLE, String.class);
            tableName = claims.get(JwtClaimsConstant.TABLE_NAME, String.class);

            // 创建包含所有属性的上下文对象
            UserContext userContext = new UserContext(userId, role, tableName, username);

            // 存储到BaseContext
            BaseContext.setUserContext(userContext);

            // 同时设置请求属性（可选）
            request.setAttribute("userId", userId);
            request.setAttribute("role", role);
            request.setAttribute("tableName", tableName);
            request.setAttribute("username", username);

            log.info("JWT验证成功，用户ID: {}", userId);
            return true;
        } catch (Exception ex) {
            log.error("JWT验证失败: {}", ex.getMessage());
            sendErrorResponse(response, 401, "无效令牌");
            return false;
        }
    }

    private void sendErrorResponse(HttpServletResponse response, int code, String message) throws IOException {
        response.setStatus(code);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write("{\"code\":" + code + ",\"msg\":\"" + message + "\"}");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        // 清除ThreadLocal，防止内存泄漏
        BaseContext.clearContext();
    }
}